package alex.edu;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class StatusService extends Service {

	public static final String NEW_STATUS_FOUND = "new status";
	private Timer updateTimer;
	private final long UPDATE_DELAY = 10000;
	static String last_date_String = "";
	public static int number_of_update;
	int server_access = 0;

	private Notification newEarthquakeNotification;
	public static final int NOTIFICATION_ID = 1;

	@Override
	public void onStart(Intent intent, int startId) {

	}

	private TimerTask doRefresh = new TimerTask() {
		public void run() {
			refreshStatuses(getString(R.string.status_feed) + "?date=["
					+ last_date_String + "]");
			
		}
		
	};
	
	
	@Override
	public void onCreate() {
		
		// intialize notification
		int icon = R.drawable.icon;
		String tickerText = "New Status Detected";
		long when = System.currentTimeMillis();
		newEarthquakeNotification = new Notification(icon, tickerText, when);
		newEarthquakeNotification.flags = newEarthquakeNotification.flags
				| Notification.FLAG_INSISTENT;

		refreshStatuses(getString(R.string.status_feed)); // to get all mails at
															// first time
		updateTimer = new Timer("StatusesUpdates");
		// initialize timer
		updateTimer.scheduleAtFixedRate(doRefresh, 0, UPDATE_DELAY);
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	private void refreshStatuses(String path) {
		// Get the XML
		server_access++;
		number_of_update = 0;
		URL url;
		try {
			String statusFeed = path;
			url = new URL(statusFeed);
			URLConnection connection;
			connection = url.openConnection();
			HttpURLConnection httpConnection = (HttpURLConnection) connection;
			int responseCode = httpConnection.getResponseCode();
			if (responseCode == HttpURLConnection.HTTP_OK) {
				InputStream in = httpConnection.getInputStream();
				DocumentBuilderFactory dbf;
				dbf = DocumentBuilderFactory.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				// Parse the earthquake feed.
				Document dom = db.parse(in);
				Element docEle = dom.getDocumentElement();
				// Clear the old earthquakes
				// Get a list of each earthquake entry.
				NodeList nl = docEle.getElementsByTagName("status");
				if (nl != null && nl.getLength() > 0) {
					String status_created = null;
					for (int i = 0; i < nl.getLength(); i += 2) {
						// get the whole tag
						Element status = (Element) nl.item(i);
						// get 'date' status element
						status_created = ((Element) status
								.getElementsByTagName("created-at").item(0))
								.getFirstChild().getNodeValue();
						// cast to date
						SimpleDateFormat sdf;
						sdf = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss'Z'");
						Date status_date = new GregorianCalendar(0, 0, 0)
								.getTime();
						try {
							status_date = sdf.parse(status_created);
							if (i == 0)
								last_date_String = status_created;
						} catch (ParseException e) {
							e.printStackTrace();
						}
						// get 'id' status element
						int status_id = Integer.parseInt(((Element) status
								.getElementsByTagName("id").item(0))
								.getFirstChild().getNodeValue());
						// inner "status" node
						String inner_status = ((Element) nl.item(i + 1))
								.getFirstChild().getNodeValue();
						Element user = (Element) status.getElementsByTagName(
								"user").item(0);
						String user_created = ((Element) user
								.getElementsByTagName("created-at").item(0))
								.getFirstChild().getNodeValue();
						// adjust date format
						Date user_date = new GregorianCalendar(0, 0, 0)
								.getTime();
						try {
							user_date = sdf.parse(user_created);
						} catch (ParseException e) {
							e.printStackTrace();
						}
						// get 'first-name' user element
						String user_first_name = ((Element) user
								.getElementsByTagName("first-name").item(0))
								.getFirstChild().getNodeValue();
						// check for null
						// get 'display_name' user element
						String user_display = ((Element) user
								.getElementsByTagName("display-name").item(0) == null) ? ((Element) user
								.getElementsByTagName("display-name").item(0))
								.getFirstChild().getNodeValue()
								: null;
						// get 'last-name' user element
						String user_last_name = ((Element) user
								.getElementsByTagName("last-name").item(0))
								.getFirstChild().getNodeValue();
						// get 'id' user element
						int user_id = Integer.parseInt(((Element) user
								.getElementsByTagName("id").item(0))
								.getFirstChild().getNodeValue());
						// create new user object
						User user_object = new User(user_date, user_display,
								user_first_name, user_id, user_last_name);
						// create new status object
						Status status_object = new Status(status_date,
								inner_status, status_id, user_object);
						// Process a newly status
						if (server_access == 1
								|| (server_access > 1 && i != nl.getLength() - 2))
							addNewStatus(status_object, i);
						number_of_update++;
					}
					if (server_access > 1 && number_of_update > 1)
						DoNotify();
				}
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} finally {
		}
	}

	private void DoNotify() {
		String svcName = Context.NOTIFICATION_SERVICE;
		NotificationManager notificationManager;
		notificationManager = (NotificationManager) getSystemService(svcName);
		Context context = getApplicationContext();
		Intent startActivityIntent = new Intent(getApplicationContext(),
				UpdateActivity.class);
		PendingIntent launchIntent = PendingIntent.getActivity(context, 0,
				startActivityIntent, 0);
		newEarthquakeNotification.setLatestEventInfo(context, "notify mobile",
				"notify mobile", launchIntent);
		newEarthquakeNotification.when = java.lang.System.currentTimeMillis();
		notificationManager.notify(NOTIFICATION_ID, newEarthquakeNotification);
	}

	private void addNewStatus(Status status, int index) {
		// ///////////////////statuses.add(status);///////////////////////
		announceNewState(status);
	}

	private void announceNewState(Status status) {

		Intent intent = new Intent(NEW_STATUS_FOUND);
		// to know number of element in case of update
		intent.putExtra("index", number_of_update);
		// to know weather update or first time
		intent.putExtra("server_acc", server_access);
		intent.putExtra("id", status.getId());
		intent.putExtra("created_at", status.getCreated_at());
		intent.putExtra("status", status.getStatus());
		intent.putExtra("id", status.getId());
		// for user
		intent.putExtra("user_created_at", status.getUser().getCreated_at());
		intent
				.putExtra("user_display_name", status.getUser()
						.getDisplay_name());
		intent.putExtra("user_first_name", status.getUser().getFirst_name());
		intent.putExtra("user_id", status.getUser().getId());
		intent.putExtra("user_last_name", status.getUser().getLast_name());
		sendBroadcast(intent);
	}

}
